package com.yarin.android.Examples_08_09;

import java.io.InputStream;
import java.io.InterruptedIOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Set;

import android.R.bool;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelUuid;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;
import java.util.UUID;
import android.bluetooth.BluetoothSocket;
import android.app.ProgressDialog;

public class BluetoothDemo extends Activity {
    /** Called when the activity is first created. */
    ListView listViewPaired;
    ListView listViewDetected;
    ArrayList<String> arrayListpaired;
    Button buttonSearch,buttonOn,buttonDesc,buttonOff;
    ArrayAdapter<String> adapter,detectedAdapter;
    static HandleSeacrh handleSeacrh;
    BluetoothDevice bdDevice;
    BluetoothClass bdClass;
    ArrayList<BluetoothDevice> arrayListPairedBluetoothDevices;
    private ButtonClicked clicked;
    ListItemClickedonPaired listItemClickedonPaired;
    BluetoothAdapter bluetoothAdapter = null;
    ArrayList<BluetoothDevice> arrayListBluetoothDevices = null;
    ListItemClicked listItemClicked;

    //private BluetoothSocket btSocket;
    public static OutputStream outStream;
    public static InputStream inputStream;
    public static boolean receiveFlag;
    public static String receiveContent = "";

    private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    private ProgressDialog progressBar;

    private volatile boolean _discoveryFinished;
    private Handler _handler = new Handler();
    private Runnable _discoveryWorkder = new Runnable() {
        public void run() {
            bluetoothAdapter.startDiscovery();
            for (;;){
                if (_discoveryFinished) {
                    break;
                }
                try {
                    Thread.sleep(100);
                }
                catch (InterruptedException e){}
            }
        }
    };

    private Runnable pairTargetWorkder = new Runnable() {
        public void run() {
            bluetoothAdapter.startDiscovery();
            for (;;) {
                if (_discoveryFinished) {
                    break;
                }
                try {
                    Thread.sleep(100);
                }
                catch (InterruptedException e){}
            }
        }
    };

    public Handler handlerWel = new Handler() {
        public void handleMessage(Message msg) {//定义一个Handler，用于处理下载线程与UI间通讯
            if (!Thread.currentThread().isInterrupted()) {
                switch (msg.what) {
                    case 1:
                        //FF7705000000000D0A
                        byte[] targetBlueOrder = {(byte)0xFF, (byte)0x77, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0D, (byte)0x0A};
                        sendBlueOrder(targetBlueOrder);
                        Intent intent = new Intent(BluetoothDemo.this, Activity02.class) ;
                        BluetoothDemo.this.startActivity(intent);
                        break;
                    case 2:
                        setTitle("receive ===>" + receiveContent);
                        break;
                    case -1:
                        break;
                }
            }
            super.handleMessage(msg);
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.demomain);
        listViewDetected = (ListView) findViewById(R.id.listViewDetected);
        listViewPaired = (ListView) findViewById(R.id.listViewPaired);
        buttonSearch = (Button) findViewById(R.id.buttonSearch);
        buttonOn = (Button) findViewById(R.id.buttonOn);
        buttonDesc = (Button) findViewById(R.id.buttonDesc);
        buttonOff = (Button) findViewById(R.id.buttonOff);
        arrayListpaired = new ArrayList<String>();
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        clicked = new ButtonClicked();
        handleSeacrh = new HandleSeacrh();
        arrayListPairedBluetoothDevices = new ArrayList<BluetoothDevice>();
        /*
         * the above declaration is just for getting the paired bluetooth devices;
         * this helps in the removing the bond between paired devices.
         */
        listItemClickedonPaired = new ListItemClickedonPaired();
        arrayListBluetoothDevices = new ArrayList<BluetoothDevice>();
        adapter= new ArrayAdapter<String>(BluetoothDemo.this, android.R.layout.simple_list_item_1, arrayListpaired);
        detectedAdapter = new ArrayAdapter<String>(BluetoothDemo.this, android.R.layout.simple_list_item_single_choice);
        listViewDetected.setAdapter(detectedAdapter);
        listItemClicked = new ListItemClicked();
        detectedAdapter.notifyDataSetChanged();
        listViewPaired.setAdapter(adapter);
    }
    @Override
    protected void onStart() {
        // TODO Auto-generated method stub
        super.onStart();
        getPairedDevices();
        buttonOn.setOnClickListener(clicked);
        buttonSearch.setOnClickListener(clicked);
        buttonDesc.setOnClickListener(clicked);
        buttonOff.setOnClickListener(clicked);
        listViewDetected.setOnItemClickListener(listItemClicked);
        listViewPaired.setOnItemClickListener(listItemClickedonPaired);
    }

    private void getPairedDevices() {
        Set<BluetoothDevice> pairedDevice = bluetoothAdapter.getBondedDevices();
        if(pairedDevice.size()>0) {
            for(BluetoothDevice device : pairedDevice) {
                arrayListpaired.add(device.getName()+"\n"+device.getAddress());
                arrayListPairedBluetoothDevices.add(device);
            }
        }
        adapter.notifyDataSetChanged();
    }

    class ListItemClicked implements OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            // TODO Auto-generated method stub
            bdDevice = arrayListBluetoothDevices.get(position);

            /*
             * here below we can do pairing without calling the callthread(), we can directly call the
             * connect(). but for the safer side we must use the threading object.
             */
            if(bdDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
                //new ConnectThread(bdDevice).start();
            }
            else {
                progressBar = new ProgressDialog(view.getContext());
                progressBar.setCancelable(true);
                progressBar.setMessage("Pairing ...");
                progressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                progressBar.show();

                //btSocket = bdDevice.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
                /*UUID uuid = bdDevice.getUuids()[0].getUuid();
                btSocket = bdDevice.createRfcommSocketToServiceRecord(uuid);*/

                Boolean isBonded = false;
                try {
                    isBonded = createBond(bdDevice);
                    if(isBonded) {
                        getPairedDevices();
                        adapter.notifyDataSetChanged();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    class ListItemClickedonPaired implements OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,long id) {
            bdDevice = arrayListPairedBluetoothDevices.get(position);
            /*try {
                Boolean removeBonding = removeBond(bdDevice);
                if(removeBonding)
                {
                    arrayListpaired.remove(position);
                    adapter.notifyDataSetChanged();
                }
                Log.i("Log", "Removed"+removeBonding);
            } catch (Exception e) {
                e.printStackTrace();
            }*/

            //try {
            //btSocket = bdDevice.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));

            /*Method m = bdDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
            btSocket = (BluetoothSocket) m.invoke(bdDevice, 1);*/

            /*} catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }*/

            //} catch (IOException e) {
            //   e.printStackTrace();
            //    setTitle("============= create socket fail");
            //}

            new ConnectThread(bdDevice).start();
            //notifyMeFriWill(1);

             //成功后进行连接
            /*try {

                //btSocket = bdDevice.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
                //btSocket.connect();

                //Log.e(TAG, " BT connection established, data transfer link open.");
                //mangeConnectedSocket(btSocket);//自定义函数进行蓝牙通信处理

            } catch (IOException e) {
                //Log.e(TAG, " Connection failed.", e);
                setTitle("============= connect fail");
            } catch (Exception eee) {
                //Log.e(TAG, " Connection failed.", e);
                setTitle("============= btSocket null");
            }*/
        }
    }
    /*private void callThread() {
        new Thread(){
            public void run() {
                Boolean isBonded = false;
                try {
                    isBonded = createBond(bdDevice);
                    if(isBonded)
                    {
                        arrayListpaired.add(bdDevice.getName()+"\n"+bdDevice.getAddress());
                        adapter.notifyDataSetChanged();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }//connect(bdDevice);
                Log.i("Log", "The bond is created: "+isBonded);
            }
        }.start();
    }*/

    private void mangeConnectedSocket(BluetoothSocket xxx) {
        String msgBufferString = "Hello";
        byte[] msgBuffer = msgBufferString.getBytes();
        try {
            OutputStream outStream = xxx.getOutputStream();
            outStream.write(msgBuffer);
        } catch (java.io.IOException e) {
            setTitle("============== OutStream send fail");
        }
    }

    private Boolean connect(BluetoothDevice bdDevice) {
        Boolean bool = false;
        try {
            Log.i("Log", "service metohd is called ");
            Class cl = Class.forName("android.bluetooth.BluetoothDevice");
            Class[] par = {};
            Method method = cl.getMethod("createBond", par);
            Object[] args = {};
            bool = (Boolean) method.invoke(bdDevice);//, args);// this invoke creates the detected devices paired.
        } catch (Exception e) {
            Log.i("Log", "Inside catch of serviceFromDevice Method");
            e.printStackTrace();
        }
        return bool.booleanValue();
    };


    public boolean removeBond(BluetoothDevice btDevice) throws Exception {
        Class btClass = Class.forName("android.bluetooth.BluetoothDevice");
        Method removeBondMethod = btClass.getMethod("removeBond");
        Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);
        return returnValue.booleanValue();
    }

    private class ConnectThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;

        public ConnectThread(BluetoothDevice device) {
            // Use a temporary object that is later assigned to mmSocket,
            // because mmSocket is final
            BluetoothSocket tmp = null;
            mmDevice = device;

            // Get a BluetoothSocket to connect with the given BluetoothDevice
            try {
                // MY_UUID is the app's UUID string, also used by the server code
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
            } catch (IOException e) {
                setTitle(" ===> create socket fail");
            }
            mmSocket = tmp;
        }

        public void run() {
            // Cancel discovery because it will slow down the connection
            //bluetoothAdapter.cancelDiscovery();

            try {
                // Connect the device through the socket. This will block
                // until it succeeds or throws an exception
                mmSocket.connect();
                outStream = mmSocket.getOutputStream();
                inputStream = mmSocket.getInputStream();
                notifyMeFriWill(1);

                receiveFlag = true;

                while(receiveFlag) {
                    receiveContent = "";
                    final byte[] bytes = new byte[256];
                    int read = -1;
                    for (; (read = inputStream.read(bytes)) > -1;) {

                        //gallery==replace
                        /*receiveContent = MathMethod.byte2HexStr(bytes);
                        String[] temporary = receiveContent.split(";");
                        Log.e("gallery ===> receive ===> ", receiveContent);

                        if(temporary[2].equalsIgnoreCase("82")) {
                            if(temporary[3].equalsIgnoreCase("01")) {
                                Activity02.volumeValueFromRadio = Integer.parseInt(temporary[4], 16);
                                notifyMsgToRadioInterface(1);
                            }
                        }*/

                        if(bytes[2] == (byte)0x82) {
                            if(bytes[3] == (byte)0x01) {
                                Activity02.volumeValueFromRadio = MathMethod.byteHEXtoInt(bytes[4]);
                                notifyMsgToRadioInterface(1);
                            }
                        }
                    }
                    notifyMeFriWill(2);
                }

            } catch (IOException connectException) {
                connectException.printStackTrace();
                try {
                    if(mmSocket != null)
                        mmSocket.close();
                    if(outStream != null)
                        outStream.close();
                    if(inputStream != null)
                        inputStream.close();
                    receiveFlag = false;
                } catch (IOException closeException) { }
                return;
            }

            // Do work to manage the connection (in a separate thread)
            //manageConnectedSocket(mmSocket);
        }

        /** Will cancel an in-progress connection, and close the socket */
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) { }
        }
    }


    public boolean createBond(BluetoothDevice btDevice) throws Exception {
        Class class1 = Class.forName("android.bluetooth.BluetoothDevice");
        Method createBondMethod = class1.getMethod("createBond");
        Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
        return returnValue.booleanValue();
    }

    class ButtonClicked implements OnClickListener {
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.buttonOn:
                    onBluetooth();
                    break;
                case R.id.buttonSearch:
                    arrayListBluetoothDevices.clear();
                    startSearching();
                    break;
                case R.id.buttonDesc:
                    makeDiscoverable();
                    break;
                case R.id.buttonOff:
                    offBluetooth();
                    break;
                default:
                    break;
            }
        }
    }

    private BroadcastReceiver myReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            Message msg = Message.obtain();
            String action = intent.getAction();
            if(BluetoothDevice.ACTION_FOUND.equals(action)){
                Toast.makeText(context, "ACTION_FOUND", Toast.LENGTH_SHORT).show();

                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                try {
                    //device.getClass().getMethod("setPairingConfirmation", boolean.class).invoke(device, true);
                    //device.getClass().getMethod("cancelPairingUserInput", boolean.class).invoke(device);
                }
                catch (Exception e) {
                    Log.i("Log", "Inside the exception: ");
                    e.printStackTrace();
                }

                if(arrayListBluetoothDevices.size()<1) // this checks if the size of bluetooth device is 0,then add the
                {                                           // device to the arraylist.
                    detectedAdapter.add(device.getName()+"\n"+device.getAddress());
                    arrayListBluetoothDevices.add(device);
                    detectedAdapter.notifyDataSetChanged();
                }
                else
                {
                    boolean flag = true;    // flag to indicate that particular device is already in the arlist or not
                    for(int i = 0; i<arrayListBluetoothDevices.size();i++)
                    {
                        if(device.getAddress().equals(arrayListBluetoothDevices.get(i).getAddress()))
                        {
                            flag = false;
                        }
                    }
                    if(flag == true)
                    {
                        detectedAdapter.add(device.getName()+"\n"+device.getAddress());
                        arrayListBluetoothDevices.add(device);
                        detectedAdapter.notifyDataSetChanged();
                    }
                }
                if(device.getName().toUpperCase().contains("RADIO")) {
                    _discoveryFinished = true;
                }
            }
        }
    };

    private void startSearching() {
        Log.i("Log", "in the start searching method");
        IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        BluetoothDemo.this.registerReceiver(myReceiver, intentFilter);

        //gallery==replace
        //bluetoothAdapter.startDiscovery();
        SamplesUtils.indeterminate(BluetoothDemo.this, _handler, "Scanning...", _discoveryWorkder, new DialogInterface.OnDismissListener() {
            public void onDismiss(DialogInterface dialog) {
                for (; bluetoothAdapter.isDiscovering();) {
                    bluetoothAdapter.cancelDiscovery();
                }
                _discoveryFinished = true;
            }
        }, true);
    }

    private void onBluetooth() {
        if(!bluetoothAdapter.isEnabled())
        {
            bluetoothAdapter.enable();
            Log.i("Log", "Bluetooth is Enabled");
        }
    }

    private void offBluetooth() {
        if(bluetoothAdapter.isEnabled())
        {
            bluetoothAdapter.disable();
        }
    }

    private void makeDiscoverable() {
        Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
        discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
        startActivity(discoverableIntent);
        Log.i("Log", "Discoverable ");
    }

    public void notifyMeFriWill(int flag) {
        Message msg = new Message();
        msg.what = flag;
        handlerWel.sendMessage(msg);
    }

    public void notifyMsgToRadioInterface(int flag) {
        Message msg = new Message();
        msg.what = flag;
        Activity02.handlerRadioInterface.sendMessage(msg);
    }

    public static void sendBlueOrder(byte[] orderBytes) {
        try {
            outStream.write(orderBytes);
            outStream.flush();
        } catch (java.io.IOException e) {
            Log.e("gallery ===> ", "============== OutStream send fail");
        }
    }

    class HandleSeacrh extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 111:
                    break;

                default:
                    break;
            }
        }
    }
}